package com.stm.bi.executor;

import com.stm.base.dto.vo.DictVO;
import com.stm.base.provider.DictionaryProvider;
import com.stm.bi.constant.DictionaryConstants;
import com.stm.bi.dto.query.SubjectListQry;
import com.stm.bi.dto.query.SubjectPageQry;
import com.stm.bi.dto.vo.SubjectCategoryInfoVO;
import com.stm.bi.dto.vo.SubjectParamVO;
import com.stm.bi.dto.vo.SubjectVO;
import com.stm.bi.repository.report.SubjectRepository;
import com.stm.bi.repository.report.SubjectCategoryRepository;
import com.stm.framework.dto.Response;
import com.stm.framework.model.CustomizePage;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 科目-查询执行器
 *
 * @author qinyongjie
 */
@Component
public class SubjectQueryExe {
    @Resource
    private SubjectRepository subjectRepository;
    @Resource
    private DictionaryProvider dictionaryProvider;
    @Resource
    private SubjectCategoryRepository subjectCategoryRepository;

    //region 主体方法区

    /**
     * 查询科目详情
     *
     * @param id 主键ID
     * @return 科目详情
     */
    public Response<SubjectVO> selectById(Long id) {
        SubjectVO subjectVO = subjectRepository.selectById(id);
        List<DictVO> dictList = dictionaryProvider.selectList(DictionaryConstants.PARAM_TYPE);

        // 拼接科目参数字符串
        subjectVO.setSubjectParamStr(buildSubjectParamStr(subjectVO.getSubjectParam(), dictList));

        return Response.of(subjectVO);
    }

    /**
     * 查询页面
     *
     * @param subjectPageQry 分页查询条件
     * @return 分页结果
     */
    public Response<CustomizePage<SubjectVO>> selectPage(SubjectPageQry subjectPageQry) {
        return Response.of(subjectRepository.selectPage(subjectPageQry));
    }

    /**
     * 查询列表
     *
     * @param subjectListQry 列表查询条件
     * @return 科目列表
     */
    public Response<List<SubjectVO>> selectList(SubjectListQry subjectListQry) {
        return Response.of(subjectRepository.selectList(subjectListQry));
    }

    /**
     * 通过归属分类ID查询科目信息（递归查询子分类）
     *
     * @param categoryId 归属分类ID
     * @return 科目信息列表
     */
    public Response<List<SubjectCategoryInfoVO>> selectByCategoryId(Long categoryId) {
        // 递归查询指定分类及其所有子分类的ID
        List<Long> allCategoryIds = subjectCategoryRepository.selectAllSubCategoryIds(categoryId);
        
        if (CollectionUtils.isEmpty(allCategoryIds)) {
            return Response.of(List.of());
        }
        
        // 查询所有相关分类下的科目
        List<SubjectVO> allSubjects = allCategoryIds.stream()
                .map(catId -> {
                    SubjectListQry qry = new SubjectListQry();
                    qry.setCategoryId(catId);
                    return subjectRepository.selectList(qry);
                })
                .flatMap(List::stream)
                .toList();

        if (CollectionUtils.isEmpty(allSubjects)) {
            return Response.of(List.of());
        }

        // 获取字典数据
        List<DictVO> dictList = dictionaryProvider.selectList(DictionaryConstants.PARAM_TYPE);

        // 转换为SubjectCategoryInfoVO
        List<SubjectCategoryInfoVO> result = allSubjects.stream()
                .map(subject -> convertToSubjectCategoryInfoVO(subject, dictList))
                .collect(Collectors.toList());

        return Response.of(result);
    }
    //endregion


    //region 私有方法区
    // 根据科目参数值和字典列表构建参数字符串，如"付款；退款；"
    private String buildSubjectParamStr(List<String> subjectParams, List<DictVO> dictList) {
        if (CollectionUtils.isEmpty(subjectParams) || CollectionUtils.isEmpty(dictList)) {
            return "";
        }

        // 从字典列表中获取所有子项
        List<DictVO> allChildren = dictList.stream()
                .filter(dict -> !CollectionUtils.isEmpty(dict.getChildren()))
                .flatMap(dict -> dict.getChildren().stream())
                .toList();

        // 根据subjectParams的值匹配对应的label并拼接
        return subjectParams.stream()
                .map(param -> allChildren.stream()
                        .filter(child -> param.equals(child.getValue()))
                        .findFirst()
                        .map(DictVO::getLabel)
                        .orElse(""))
                .filter(label -> !label.isEmpty())
                .collect(Collectors.joining("；", "", "；"));
    }

    // 将SubjectVO转换为SubjectCategoryInfoVO
    private SubjectCategoryInfoVO convertToSubjectCategoryInfoVO(SubjectVO subject, List<DictVO> dictList) {
        SubjectCategoryInfoVO result = new SubjectCategoryInfoVO();
        result.setId(subject.getId())
                .setName(subject.getName())
                .setSubjectCode(subject.getSubjectCode())
                .setCategoryId(subject.getCategoryId())
                .setFieldName(subject.getFieldName())
                .setChecked(false); // 固定设为false

        // 构建参数列表
        List<SubjectParamVO> paramList = buildParamList(subject.getSubjectParam(), dictList);
        result.setParamList(paramList);

        return result;
    }

    // 构建参数列表
    private List<SubjectParamVO> buildParamList(List<String> subjectParams, List<DictVO> dictList) {
        if (CollectionUtils.isEmpty(dictList) || CollectionUtils.isEmpty(subjectParams)) {
            return List.of();
        }

        // 从字典列表中获取所有子项
        List<DictVO> allChildren = dictList.stream()
                .filter(dict -> !CollectionUtils.isEmpty(dict.getChildren()))
                .flatMap(dict -> dict.getChildren().stream())
                .toList();

        // 只返回科目参数中包含的字典项
        return subjectParams.stream()
                .map(param -> allChildren.stream()
                        .filter(child -> param.equals(child.getValue()))
                        .findFirst()
                        .map(child -> {
                            SubjectParamVO paramVO = new SubjectParamVO();
                            paramVO.setValue(child.getValue())
                                    .setLabel(child.getLabel())
                                    .setChecked(false); // 固定设为false
                            return paramVO;
                        })
                        .orElse(null))
                .filter(Objects::nonNull)
                .collect(Collectors.toList());
    }
    //endregion
}
